知识点名称:AsyncTask的使用

编号: K10-3

前驱知识点编号:K10-2,K3-1

作者:

AsyncTask和Handler的功能都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,但它比Handler在代码上更轻量级一些,也就是更简单易用,由于AsyncTask使用了线程池,所以它比较耗费资源,只有当异步任务数量庞大时,才能充分体现AsyncTask的优势。下面我们先通过实例看AsyncTask是如何实现异步处理的。

AsyncTask是抽象类,因此,我们首先要通过继承它,定义自己的异步类,然后,在实现耗时操作的地方调用自定义的AsyncTask类。

1. AsyncTask类

AsyncTask定义了三种泛型类型,其中:

Params:是启动任务执行的输入参数,比如要实现异步下载,该参数可能传入的是下载的URL值,如果不需要传递参数,可以设置为void.

Progress:后台任务(或称为子线程)执行的百分比

  Result:后台执行任务结果的返回值类型。和doInBackground()方法的返回值类型保持一致。

AsyncTask类中的方法:

在此,结合一个异步任务执行的一般过程来分析AsyncTask类中所包含的方法。

1) onPreExecute()方法:执行一个异步任务,需要首先在代码中调用execute(Params... params)方法,来触发异步任务的执行,异步任务执行就会自动回调onPreExecute(),该方法一般用来在执行后台任务前对UI做一些标记。

2) doInBackground(Params... params)方法:在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。

3) onProgressUpdate(Progress... values)方法:在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。

4) onPostExecute(Result result) 方法:当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。

以上四个方法会被自动回调,无需手动调用,否则会出错。另外,还有onCancelled()方法,用来执行用户调用取消时,要做的操作。

2.自定义AsyncTask类

自定义的AsyncTask类要继承AsyncTask<Params,Progress,Result>,并实现其中的某些方法。

下面用AsyncTask类来实现在Handler中进度条更新的例题。

//模拟网络环境  
   public class NetOperator {  

       public void operator(){  
           try {  
               //休眠1秒  
               Thread.sleep(1000);  
           } catch (InterruptedException e) {  
               // TODO Auto-generated catch block  
               e.printStackTrace();  
           }  
       }  

   }  
   class ProgressBarAsyncTask extends AsyncTask<Integer, Integer, String>{

        private Button button;  
        private ProgressBar progressBar;  

        public ProgressBarAsyncTask(Button button, ProgressBar progressBar) {  
            super();  
            this.button=button;  
            this.progressBar = progressBar;  
        }  
        /**  
         * 这里的Integer参数对应AsyncTask中的第一个参数   
         * 这里的String返回值对应AsyncTask的第三个参数  
         * 该方法并不运行在UI线程当中,主要用于异步操作,所有在该方法中不能对UI当中的空间进行设置和修改  
         * 但是可以调用publishProgress方法触发onProgressUpdate对UI进行操作  
         */  
    protected String doInBackground(Integer... params) {
        // TODO Auto-generated method stub
          NetOperator netOperator = new NetOperator();  
            int i = 0;  
            for (i = 10; i <= 100; i+=10) {  
                netOperator.operator();  
                publishProgress(i);  
            }  
            return i + params[0].intValue() + "";  
    }
     /**  
     * 这里的String参数对应AsyncTask中的第三个参数(也就是接收doInBackground的返回值)  
     * 在doInBackground方法执行结束之后在运行,并且运行在UI线程当中 可以对UI空间进行设置  
     */  
    @Override  
    protected void onPostExecute(String result) {  
        System.out.println("异步操作执行结束" + result);  
    }  
    //该方法运行在UI线程当中,并且运行在UI线程当中 可以对UI空间进行设置  
    @Override  
    protected void onPreExecute() {  
        System.out.println("开始执行异步线程");  
    }  
    /**  
     * 这里的Intege参数对应AsyncTask中的第二个参数  
     * 在doInBackground方法当中,,每次调用publishProgress方法都会触发onProgressUpdate执行  
     * onProgressUpdate是在UI线程中执行,所有可以对UI空间进行操作  
     */  
    @Override  
    protected void onProgressUpdate(Integer... values) {  
        int vlaue = values[0]; 
        progressBar.setProgress(vlaue);  
    }  
   }
}

下面演示对自定义的AsyncTask类的调用

public class MainActivity extends ActionBarActivity {
    private Button button;
    private ProgressBar progressBar;
   public void onCreate(Bundle savedInstanceState)  
   {  
       super.onCreate(savedInstanceState);  
       setContentView(R.layout.activity_main); 
       button = (Button)findViewById(R.id.button1);  
       progressBar = (ProgressBar)findViewById(R.id.progressBar1);  
       button.setOnClickListener(new OnClickListener() {  
           public void onClick(View v) {  
               ProgressBarAsyncTask asyncTask = new ProgressBarAsyncTask(button, progressBar);  

               asyncTask.execute(1000);  
           }  
       });  
   }

自此,我们知道Android系统为了提高程序的实时响应能力,不允许在UI线程中进行耗时的操作,否则会出现ANR异常,因此必须将耗时的任务放到非UI线程中执行。Android提供了很多类来帮助大家完成异步操作,比如:Thread类, AsyncTask类,Handler类等,本章就这些类给出了详细的使用,并介绍了它们之间的区别。

results matching ""

    No results matching ""